using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace SmartClientPlatform.RemoteClientBase
{
    [Serializable]
    internal class DataStore : ISerializable, IDataChanger
    {
        private object dataContainer;

        internal DataContainer<T> Wrap<T>(Func<DataContainer<T>> func)
        {
            if (dataContainer == null)
            {
                var container = func();
                dataContainer = container;
                container.DataStore = this;
                return container;
            }
            else
            {
                return (DataContainer<T>)dataContainer;
            }
        }

        private readonly Dictionary<string, object> properties = new Dictionary<string, object>();

        internal bool TryGetValue(string propertyName, out object value)
        {
            return properties.TryGetValue(propertyName, out value);
        }

        internal object this[string propertyName]
        {
            set
            {
                properties[propertyName] = value;
            }
        }

        internal void Add(string propertyName, object value)
        {
            properties.Add(propertyName, value);
        }

        public void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
        {
            foreach (var keyValuePair in properties)
            {
                serializationInfo.AddValue(keyValuePair.Key, keyValuePair.Value);
            }
        }

        private DataStore(SerializationInfo serializationInfo, StreamingContext streamingContext)
            : this()
        {
            foreach (var serializationEntry in serializationInfo)
            {
                properties.Add(serializationEntry.Name, serializationEntry.Value);
            }
        }

        internal DataStore()
        {
            //no-op
        }

        [OnDeserialized]
        private void OnDeserialized(StreamingContext context)
        {
            ChangesTracker.OnDeserializedDataStore(this);
        }

        public event Action<IChangeProvider> Change;

        internal void DoChange(IChangeProvider changeProvider)
        {
            if (Change != null) Change(changeProvider);
        }
    }
}